package com.wy2.generator.database;


import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;

import cn.xo68.core.util.StringTools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


import com.wy2.generator.config.DatabaseConsts;
import com.wy2.generator.resource.Messages;


/**
 * This class assumes that classes are cached elsewhere for performance reasons,
 * but also to make sure that any native libraries are only loaded one time
 * (avoids the dreaded UnsatisfiedLinkError library loaded in another
 * classloader)
 * 
 * @author Jeff Butler
 */
public class JdbcConnectionFactory implements ConnectionFactory {
	
	private static final Logger logger=LoggerFactory.getLogger(JdbcConnectionFactory.class);

	private String catalog;
	private String schema;
	
    private String userId;
    private String password;
    private String connectionURL;
    private String driverClass;
    private Properties otherProperties;

    /**
     * This constructor is called when there is a JDBCConnectionConfiguration
     * specified in the configuration.
     * 
     * @param config
     */
    public JdbcConnectionFactory(JdbcConnectionConfiguration config) {
        super();
        this.catalog=config.getCatalog();
        this.schema=config.getSchema();
        userId = config.getUserId();
        password = config.getPassword();
        connectionURL = config.getConnectionURL();
        driverClass = config.getDriverClass();
        otherProperties = config.getProperties();
    }
    
    /**
     * This constructor is called when this connection factory is specified 
     * as the type in a ConnectionFactory configuration element. 
     */
    public JdbcConnectionFactory() {
        super();
    }

    public Connection getConnection()
            throws SQLException {
        Driver driver = getDriver();

        Properties props = new Properties();

        if (StringTools.isNotEmpty(userId)) {
            props.setProperty(DatabaseConsts.CONNECT_USER, userId); //$NON-NLS-1$
        }

        if (StringTools.isNotEmpty(password)) {
            props.setProperty(DatabaseConsts.CONNECT_PASSWORD, password); //$NON-NLS-1$
        }
        
        if (StringTools.isNotEmpty(catalog)) {
            props.setProperty(DatabaseConsts.CONNECT_CATALOG, catalog); //$NON-NLS-1$
        }
        
        if (StringTools.isNotEmpty(schema)) {
            props.setProperty(DatabaseConsts.CONNECT_SCHEMA, schema); //$NON-NLS-1$
        }
        
        

        props.putAll(otherProperties);
        logger.info("start connect database...");
        Connection conn =driver.connect(connectionURL, props);
         //DriverManager.getConnection(connectionURL,userId,password); 
        //driver.connect(connectionURL, props);
        

        if (conn == null) {
        	logger.error(Messages.getString("RuntimeError.1"));
            throw new SQLException(Messages.getString("RuntimeError.1")); //$NON-NLS-1$
        }

        return conn;
    }

    private Driver getDriver() {
        Driver driver;

        try {
            Class<?> clazz =Class.forName(driverClass);
            // ObjectFactory.externalClassForName(driverClass);
            driver = (Driver) clazz.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(Messages.getString("RuntimeError.8"), e); //$NON-NLS-1$
        }

        return driver;
    }

    public void addConfigurationProperties(Properties properties) {
        // this should only be called when this connection factory is
        // specified in a ConnectionFactory configuration
        userId = properties.getProperty(DatabaseConsts.CONFIG_CONNECT_USER_ID);
        password = properties.getProperty(DatabaseConsts.CONFIG_CONNECT_PASSWORD);
        connectionURL = properties.getProperty(DatabaseConsts.CONFIG_CONNECT_CONNECTION_URL);
        driverClass = properties.getProperty(DatabaseConsts.CONFIG_CONNECT_DRIVER_CLASS);
        catalog = properties.getProperty(DatabaseConsts.CONFIG_CONNECT_CATALOG);
        schema = properties.getProperty(DatabaseConsts.CONFIG_CONNECT_SCHEMA);
        
        otherProperties = new Properties();
        otherProperties.putAll(properties);
        
        // remove all the properties that we have specific attributes for
        otherProperties.remove(DatabaseConsts.CONFIG_CONNECT_USER_ID);
        otherProperties.remove(DatabaseConsts.CONFIG_CONNECT_PASSWORD);
        otherProperties.remove(DatabaseConsts.CONFIG_CONNECT_CONNECTION_URL);
        otherProperties.remove(DatabaseConsts.CONFIG_CONNECT_DRIVER_CLASS);
        otherProperties.remove(DatabaseConsts.CONFIG_CONNECT_CATALOG);
        otherProperties.remove(DatabaseConsts.CONFIG_CONNECT_SCHEMA);
    }
}
